Skip to content

feat: make MoneyAccountUpgradeController own its bootstrap - #10072

Merged
Jwhiles merged 10 commits into
mainfrom
money-account-upgrade-controller-owned-bootstrap
Sep 4, 2026
Merged

feat: make MoneyAccountUpgradeController own its bootstrap#10072
Jwhiles merged 10 commits into
mainfrom
money-account-upgrade-controller-owned-bootstrap

Conversation

@Jwhiles

@Jwhiles Jwhiles commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Explanation

This updates the money account upgrade controller to make it better able to handle its own initialisation. At the moment clients have to manage initialising the controller, leading to a lot of shared code. This PR tries to move that logic into the controller itself as much as possible

Key changes:

  • The controller subscribes to RemoteFeatureFlagController:stateChanged and KeyringController:stateChanged and uses this information to bootstrap itself.
  • BREAKING: init() now takes no arguments, and merely sets up subscriptions to to some messenger events.
  • BREAKING: the constructor requires a hooks option for the parts of the upgrade flow that can only be determined in the client.
  • upgradeAccount() waits for an in-flight bootstrap instead of throwing (replacing mobile's module-level whenMoneyAccountUpgradeReady promise), and is disarmed when isEnabled flips off so it cannot run against a stale config.
  • A public sync() lets clients re-trigger the bootstraps checks from client-only signals - for example onboarding being completed.
  • Vault-config parsing/validation and comparison move to @metamask/money-account-utils (getMoneyAccountVaultConfig, parseMoneyAccountVaultConfig, areMoneyAccountVaultConfigsEqual, MoneyAccountVaultConfig), shared by the controller and both clients.

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed, highlighting breaking changes as necessary
  • I've prepared draft pull requests for clients and consumer packages to resolve any breaking changes

Note

High Risk
Breaking API and messenger wiring for all clients, plus signing/EIP-7702 upgrade flows that depend on serialized bootstrap and config disarm logic; incorrect integration could block upgrades or sign against wrong vault config.

Overview
MoneyAccountUpgradeController now bootstraps itself instead of requiring clients to call init({ chainId, boringVaultAddress }). After a one-time, no-arg init(), it listens to remote feature flags and keyring state, gates on client hooks (isEnabled, optional isEligible, ensureChainConfigured, onBootstrapError), parses moneyAccountVaultConfig, and arms upgrade config from CHOMP. A public sync() re-runs those gates for client-only signals (e.g. onboarding).

Breaking consumer changes: constructor must pass hooks; messenger must allow RemoteFeatureFlagController:getState, KeyringController:getState, and the corresponding stateChange events. upgradeAccount() waits for in-flight bootstrap, refuses when disarmed (feature off, failed bootstrap, locked wallet), and aborts mid-sequence if the vault config is superseded—so delegations are not signed against a stale vault.

Vault flag parsing moves to @metamask/money-account-utils (getMoneyAccountVaultConfig, parseMoneyAccountVaultConfig, areMoneyAccountVaultConfigsEqual, MissingMoneyAccountVaultConfigError surfaced via onBootstrapError once when the flag is missing/malformed).

Reviewed by Cursor Bugbot for commit 0046818. Bugbot is set up for automated code reviews on this repo. Configure here.

@Jwhiles

Jwhiles commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

1 similar comment
@Jwhiles

Jwhiles commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@8.0.0-preview-7e951bf
@metamask-previews/accounts-controller@39.1.1-preview-7e951bf
@metamask-previews/address-book-controller@7.1.2-preview-7e951bf
@metamask-previews/ai-controllers@1.0.0-preview-7e951bf
@metamask-previews/analytics-controller@2.0.0-preview-7e951bf
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-7e951bf
@metamask-previews/announcement-controller@8.1.0-preview-7e951bf
@metamask-previews/app-metadata-controller@2.0.1-preview-7e951bf
@metamask-previews/approval-controller@9.0.2-preview-7e951bf
@metamask-previews/assets-controller@14.0.3-preview-7e951bf
@metamask-previews/assets-controllers@111.1.3-preview-7e951bf
@metamask-previews/authenticated-user-storage@3.0.2-preview-7e951bf
@metamask-previews/base-controller@9.1.0-preview-7e951bf
@metamask-previews/base-data-service@1.0.0-preview-7e951bf
@metamask-previews/bitcoin-regtest-up@1.0.0-preview-7e951bf
@metamask-previews/bridge-controller@80.1.1-preview-7e951bf
@metamask-previews/bridge-status-controller@75.4.0-preview-7e951bf
@metamask-previews/build-utils@3.0.4-preview-7e951bf
@metamask-previews/chain-agnostic-permission@1.7.0-preview-7e951bf
@metamask-previews/chomp-api-service@4.0.1-preview-7e951bf
@metamask-previews/claims-controller@0.6.1-preview-7e951bf
@metamask-previews/client-controller@1.0.1-preview-7e951bf
@metamask-previews/client-utils@2.1.1-preview-7e951bf
@metamask-previews/compliance-controller@2.1.0-preview-7e951bf
@metamask-previews/composable-controller@12.0.1-preview-7e951bf
@metamask-previews/config-registry-controller@3.1.0-preview-7e951bf
@metamask-previews/connectivity-controller@0.3.0-preview-7e951bf
@metamask-previews/controller-utils@12.3.0-preview-7e951bf
@metamask-previews/core-backend@9.0.0-preview-7e951bf
@metamask-previews/delegation-controller@3.0.2-preview-7e951bf
@metamask-previews/earn-controller@12.2.6-preview-7e951bf
@metamask-previews/eip-5792-middleware@3.0.5-preview-7e951bf
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.1-preview-7e951bf
@metamask-previews/eip1193-permission-middleware@2.0.1-preview-7e951bf
@metamask-previews/eth-block-tracker@15.0.1-preview-7e951bf
@metamask-previews/eth-json-rpc-middleware@24.0.2-preview-7e951bf
@metamask-previews/eth-json-rpc-provider@6.0.1-preview-7e951bf
@metamask-previews/foundryup@1.0.1-preview-7e951bf
@metamask-previews/gas-fee-controller@26.3.2-preview-7e951bf
@metamask-previews/gator-permissions-controller@5.0.2-preview-7e951bf
@metamask-previews/geolocation-controller@1.0.0-preview-7e951bf
@metamask-previews/java-tron-up@1.0.0-preview-7e951bf
@metamask-previews/json-rpc-engine@10.5.0-preview-7e951bf
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-7e951bf
@metamask-previews/keyring-controller@27.1.1-preview-7e951bf
@metamask-previews/kyc-controller@0.0.0-preview-7e951bf
@metamask-previews/local-node-utils@1.0.0-preview-7e951bf
@metamask-previews/logging-controller@9.0.0-preview-7e951bf
@metamask-previews/message-manager@14.1.2-preview-7e951bf
@metamask-previews/messenger@2.0.0-preview-7e951bf
@metamask-previews/messenger-cli@0.2.0-preview-7e951bf
@metamask-previews/money-account-api-data-service@0.4.1-preview-7e951bf
@metamask-previews/money-account-balance-service@2.4.3-preview-7e951bf
@metamask-previews/money-account-controller@1.0.0-preview-7e951bf
@metamask-previews/money-account-upgrade-controller@3.0.2-preview-7e951bf
@metamask-previews/money-account-utils@1.1.0-preview-7e951bf
@metamask-previews/multichain-account-service@13.0.2-preview-7e951bf
@metamask-previews/multichain-api-middleware@4.0.3-preview-7e951bf
@metamask-previews/multichain-network-controller@3.2.4-preview-7e951bf
@metamask-previews/multichain-transactions-controller@7.1.2-preview-7e951bf
@metamask-previews/name-controller@9.1.2-preview-7e951bf
@metamask-previews/network-connection-banner-controller@0.2.1-preview-7e951bf
@metamask-previews/network-controller@36.0.0-preview-7e951bf
@metamask-previews/network-enablement-controller@6.0.5-preview-7e951bf
@metamask-previews/notification-services-controller@26.0.1-preview-7e951bf
@metamask-previews/passkey-controller@3.1.0-preview-7e951bf
@metamask-previews/permission-controller@13.1.1-preview-7e951bf
@metamask-previews/permission-log-controller@5.1.0-preview-7e951bf
@metamask-previews/perps-controller@15.1.0-preview-7e951bf
@metamask-previews/phishing-controller@17.4.0-preview-7e951bf
@metamask-previews/platform-api-docs@0.1.0-preview-7e951bf
@metamask-previews/polling-controller@16.0.9-preview-7e951bf
@metamask-previews/preferences-controller@23.1.0-preview-7e951bf
@metamask-previews/profile-metrics-controller@4.0.3-preview-7e951bf
@metamask-previews/profile-sync-controller@29.0.0-preview-7e951bf
@metamask-previews/ramps-controller@20.2.0-preview-7e951bf
@metamask-previews/rate-limit-controller@7.0.1-preview-7e951bf
@metamask-previews/react-data-query@1.0.0-preview-7e951bf
@metamask-previews/remote-feature-flag-controller@6.1.0-preview-7e951bf
@metamask-previews/sample-controllers@5.0.6-preview-7e951bf
@metamask-previews/seedless-onboarding-controller@10.1.1-preview-7e951bf
@metamask-previews/selected-network-controller@26.1.7-preview-7e951bf
@metamask-previews/sentinel-api-service@1.0.1-preview-7e951bf
@metamask-previews/shield-controller@6.0.1-preview-7e951bf
@metamask-previews/signature-controller@39.2.10-preview-7e951bf
@metamask-previews/smart-transactions-controller@26.0.0-preview-7e951bf
@metamask-previews/snap-account-service@2.1.2-preview-7e951bf
@metamask-previews/social-controllers@2.8.0-preview-7e951bf
@metamask-previews/solana-test-validator-up@1.0.0-preview-7e951bf
@metamask-previews/stellar-quickstart-up@0.0.0-preview-7e951bf
@metamask-previews/storage-service@1.0.2-preview-7e951bf
@metamask-previews/subscription-controller@8.0.1-preview-7e951bf
@metamask-previews/transaction-controller@69.7.0-preview-7e951bf
@metamask-previews/transaction-pay-controller@27.1.1-preview-7e951bf
@metamask-previews/user-operation-controller@41.2.9-preview-7e951bf
@metamask-previews/wallet@12.0.2-preview-7e951bf
@metamask-previews/wallet-cli@0.0.0-preview-7e951bf

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@8.0.0-preview-6b7c25c
@metamask-previews/accounts-controller@39.1.1-preview-6b7c25c
@metamask-previews/address-book-controller@7.1.2-preview-6b7c25c
@metamask-previews/ai-controllers@1.0.0-preview-6b7c25c
@metamask-previews/analytics-controller@2.0.0-preview-6b7c25c
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-6b7c25c
@metamask-previews/announcement-controller@8.1.0-preview-6b7c25c
@metamask-previews/app-metadata-controller@2.0.1-preview-6b7c25c
@metamask-previews/approval-controller@9.0.2-preview-6b7c25c
@metamask-previews/assets-controller@14.0.3-preview-6b7c25c
@metamask-previews/assets-controllers@111.1.3-preview-6b7c25c
@metamask-previews/authenticated-user-storage@3.0.2-preview-6b7c25c
@metamask-previews/base-controller@9.1.0-preview-6b7c25c
@metamask-previews/base-data-service@1.0.0-preview-6b7c25c
@metamask-previews/bitcoin-regtest-up@1.0.0-preview-6b7c25c
@metamask-previews/bridge-controller@80.1.1-preview-6b7c25c
@metamask-previews/bridge-status-controller@75.4.0-preview-6b7c25c
@metamask-previews/build-utils@3.0.4-preview-6b7c25c
@metamask-previews/chain-agnostic-permission@1.7.0-preview-6b7c25c
@metamask-previews/chomp-api-service@4.0.1-preview-6b7c25c
@metamask-previews/claims-controller@0.6.1-preview-6b7c25c
@metamask-previews/client-controller@1.0.1-preview-6b7c25c
@metamask-previews/client-utils@2.1.1-preview-6b7c25c
@metamask-previews/compliance-controller@2.1.0-preview-6b7c25c
@metamask-previews/composable-controller@12.0.1-preview-6b7c25c
@metamask-previews/config-registry-controller@3.1.0-preview-6b7c25c
@metamask-previews/connectivity-controller@0.3.0-preview-6b7c25c
@metamask-previews/controller-utils@12.3.0-preview-6b7c25c
@metamask-previews/core-backend@9.0.0-preview-6b7c25c
@metamask-previews/delegation-controller@3.0.2-preview-6b7c25c
@metamask-previews/earn-controller@12.2.6-preview-6b7c25c
@metamask-previews/eip-5792-middleware@3.0.5-preview-6b7c25c
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.1-preview-6b7c25c
@metamask-previews/eip1193-permission-middleware@2.0.1-preview-6b7c25c
@metamask-previews/eth-block-tracker@15.0.1-preview-6b7c25c
@metamask-previews/eth-json-rpc-middleware@24.0.2-preview-6b7c25c
@metamask-previews/eth-json-rpc-provider@6.0.1-preview-6b7c25c
@metamask-previews/foundryup@1.0.1-preview-6b7c25c
@metamask-previews/gas-fee-controller@26.3.2-preview-6b7c25c
@metamask-previews/gator-permissions-controller@5.0.2-preview-6b7c25c
@metamask-previews/geolocation-controller@1.0.0-preview-6b7c25c
@metamask-previews/java-tron-up@1.0.0-preview-6b7c25c
@metamask-previews/json-rpc-engine@10.5.0-preview-6b7c25c
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-6b7c25c
@metamask-previews/keyring-controller@27.1.1-preview-6b7c25c
@metamask-previews/kyc-controller@0.0.0-preview-6b7c25c
@metamask-previews/local-node-utils@1.0.0-preview-6b7c25c
@metamask-previews/logging-controller@9.0.0-preview-6b7c25c
@metamask-previews/message-manager@14.1.2-preview-6b7c25c
@metamask-previews/messenger@2.0.0-preview-6b7c25c
@metamask-previews/messenger-cli@0.2.0-preview-6b7c25c
@metamask-previews/money-account-api-data-service@0.4.1-preview-6b7c25c
@metamask-previews/money-account-balance-service@2.4.3-preview-6b7c25c
@metamask-previews/money-account-controller@1.0.0-preview-6b7c25c
@metamask-previews/money-account-upgrade-controller@3.0.2-preview-6b7c25c
@metamask-previews/money-account-utils@1.1.0-preview-6b7c25c
@metamask-previews/multichain-account-service@13.0.2-preview-6b7c25c
@metamask-previews/multichain-api-middleware@4.0.3-preview-6b7c25c
@metamask-previews/multichain-network-controller@3.2.4-preview-6b7c25c
@metamask-previews/multichain-transactions-controller@7.1.2-preview-6b7c25c
@metamask-previews/name-controller@9.1.2-preview-6b7c25c
@metamask-previews/network-connection-banner-controller@0.2.1-preview-6b7c25c
@metamask-previews/network-controller@36.0.0-preview-6b7c25c
@metamask-previews/network-enablement-controller@6.0.5-preview-6b7c25c
@metamask-previews/notification-services-controller@26.0.1-preview-6b7c25c
@metamask-previews/passkey-controller@3.1.0-preview-6b7c25c
@metamask-previews/permission-controller@13.1.1-preview-6b7c25c
@metamask-previews/permission-log-controller@5.1.0-preview-6b7c25c
@metamask-previews/perps-controller@15.1.0-preview-6b7c25c
@metamask-previews/phishing-controller@17.4.0-preview-6b7c25c
@metamask-previews/platform-api-docs@0.1.0-preview-6b7c25c
@metamask-previews/polling-controller@16.0.9-preview-6b7c25c
@metamask-previews/preferences-controller@23.1.0-preview-6b7c25c
@metamask-previews/profile-metrics-controller@4.0.3-preview-6b7c25c
@metamask-previews/profile-sync-controller@29.0.0-preview-6b7c25c
@metamask-previews/ramps-controller@20.2.0-preview-6b7c25c
@metamask-previews/rate-limit-controller@7.0.1-preview-6b7c25c
@metamask-previews/react-data-query@1.0.0-preview-6b7c25c
@metamask-previews/remote-feature-flag-controller@6.1.0-preview-6b7c25c
@metamask-previews/sample-controllers@5.0.6-preview-6b7c25c
@metamask-previews/seedless-onboarding-controller@10.1.1-preview-6b7c25c
@metamask-previews/selected-network-controller@26.1.7-preview-6b7c25c
@metamask-previews/sentinel-api-service@1.0.1-preview-6b7c25c
@metamask-previews/shield-controller@6.0.1-preview-6b7c25c
@metamask-previews/signature-controller@39.2.10-preview-6b7c25c
@metamask-previews/smart-transactions-controller@26.0.0-preview-6b7c25c
@metamask-previews/snap-account-service@2.1.2-preview-6b7c25c
@metamask-previews/social-controllers@2.8.0-preview-6b7c25c
@metamask-previews/solana-test-validator-up@1.0.0-preview-6b7c25c
@metamask-previews/stellar-quickstart-up@0.0.0-preview-6b7c25c
@metamask-previews/storage-service@1.0.2-preview-6b7c25c
@metamask-previews/subscription-controller@8.0.1-preview-6b7c25c
@metamask-previews/transaction-controller@69.7.0-preview-6b7c25c
@metamask-previews/transaction-pay-controller@27.1.1-preview-6b7c25c
@metamask-previews/user-operation-controller@41.2.9-preview-6b7c25c
@metamask-previews/wallet@12.0.2-preview-6b7c25c
@metamask-previews/wallet-cli@0.0.0-preview-6b7c25c

@Jwhiles

Jwhiles commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@8.0.0-preview-1ee21f9e0
@metamask-previews/accounts-controller@39.1.1-preview-1ee21f9e0
@metamask-previews/address-book-controller@7.1.2-preview-1ee21f9e0
@metamask-previews/ai-controllers@1.0.0-preview-1ee21f9e0
@metamask-previews/analytics-controller@2.0.0-preview-1ee21f9e0
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-1ee21f9e0
@metamask-previews/announcement-controller@8.1.0-preview-1ee21f9e0
@metamask-previews/app-metadata-controller@2.0.1-preview-1ee21f9e0
@metamask-previews/approval-controller@9.0.2-preview-1ee21f9e0
@metamask-previews/assets-controller@14.0.3-preview-1ee21f9e0
@metamask-previews/assets-controllers@111.1.3-preview-1ee21f9e0
@metamask-previews/authenticated-user-storage@3.0.2-preview-1ee21f9e0
@metamask-previews/base-controller@9.1.0-preview-1ee21f9e0
@metamask-previews/base-data-service@1.0.0-preview-1ee21f9e0
@metamask-previews/bitcoin-regtest-up@1.0.0-preview-1ee21f9e0
@metamask-previews/bridge-controller@80.1.1-preview-1ee21f9e0
@metamask-previews/bridge-status-controller@75.4.0-preview-1ee21f9e0
@metamask-previews/build-utils@3.0.4-preview-1ee21f9e0
@metamask-previews/chain-agnostic-permission@1.7.0-preview-1ee21f9e0
@metamask-previews/chomp-api-service@4.0.1-preview-1ee21f9e0
@metamask-previews/claims-controller@0.6.1-preview-1ee21f9e0
@metamask-previews/client-controller@1.0.1-preview-1ee21f9e0
@metamask-previews/client-utils@2.1.1-preview-1ee21f9e0
@metamask-previews/compliance-controller@2.1.0-preview-1ee21f9e0
@metamask-previews/composable-controller@12.0.1-preview-1ee21f9e0
@metamask-previews/config-registry-controller@3.1.0-preview-1ee21f9e0
@metamask-previews/connectivity-controller@0.3.0-preview-1ee21f9e0
@metamask-previews/controller-utils@12.3.0-preview-1ee21f9e0
@metamask-previews/core-backend@9.0.0-preview-1ee21f9e0
@metamask-previews/delegation-controller@3.0.2-preview-1ee21f9e0
@metamask-previews/earn-controller@12.2.6-preview-1ee21f9e0
@metamask-previews/eip-5792-middleware@3.0.5-preview-1ee21f9e0
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.1-preview-1ee21f9e0
@metamask-previews/eip1193-permission-middleware@2.0.1-preview-1ee21f9e0
@metamask-previews/eth-block-tracker@15.0.1-preview-1ee21f9e0
@metamask-previews/eth-json-rpc-middleware@24.0.2-preview-1ee21f9e0
@metamask-previews/eth-json-rpc-provider@6.0.1-preview-1ee21f9e0
@metamask-previews/foundryup@1.0.1-preview-1ee21f9e0
@metamask-previews/gas-fee-controller@26.3.2-preview-1ee21f9e0
@metamask-previews/gator-permissions-controller@5.0.2-preview-1ee21f9e0
@metamask-previews/geolocation-controller@1.0.0-preview-1ee21f9e0
@metamask-previews/java-tron-up@1.0.0-preview-1ee21f9e0
@metamask-previews/json-rpc-engine@10.5.0-preview-1ee21f9e0
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-1ee21f9e0
@metamask-previews/keyring-controller@27.1.1-preview-1ee21f9e0
@metamask-previews/kyc-controller@0.0.0-preview-1ee21f9e0
@metamask-previews/local-node-utils@1.0.0-preview-1ee21f9e0
@metamask-previews/logging-controller@9.0.0-preview-1ee21f9e0
@metamask-previews/message-manager@14.1.2-preview-1ee21f9e0
@metamask-previews/messenger@2.0.0-preview-1ee21f9e0
@metamask-previews/messenger-cli@0.2.0-preview-1ee21f9e0
@metamask-previews/money-account-api-data-service@0.4.1-preview-1ee21f9e0
@metamask-previews/money-account-balance-service@2.4.3-preview-1ee21f9e0
@metamask-previews/money-account-controller@1.0.0-preview-1ee21f9e0
@metamask-previews/money-account-upgrade-controller@3.0.2-preview-1ee21f9e0
@metamask-previews/money-account-utils@1.1.0-preview-1ee21f9e0
@metamask-previews/multichain-account-service@13.0.2-preview-1ee21f9e0
@metamask-previews/multichain-api-middleware@4.0.3-preview-1ee21f9e0
@metamask-previews/multichain-network-controller@3.2.4-preview-1ee21f9e0
@metamask-previews/multichain-transactions-controller@7.1.2-preview-1ee21f9e0
@metamask-previews/name-controller@9.1.2-preview-1ee21f9e0
@metamask-previews/network-connection-banner-controller@0.2.1-preview-1ee21f9e0
@metamask-previews/network-controller@36.0.0-preview-1ee21f9e0
@metamask-previews/network-enablement-controller@6.0.5-preview-1ee21f9e0
@metamask-previews/notification-services-controller@26.0.1-preview-1ee21f9e0
@metamask-previews/passkey-controller@3.1.0-preview-1ee21f9e0
@metamask-previews/permission-controller@13.1.1-preview-1ee21f9e0
@metamask-previews/permission-log-controller@5.1.0-preview-1ee21f9e0
@metamask-previews/perps-controller@15.1.0-preview-1ee21f9e0
@metamask-previews/phishing-controller@17.4.0-preview-1ee21f9e0
@metamask-previews/platform-api-docs@0.1.0-preview-1ee21f9e0
@metamask-previews/polling-controller@16.0.9-preview-1ee21f9e0
@metamask-previews/preferences-controller@23.1.0-preview-1ee21f9e0
@metamask-previews/profile-metrics-controller@4.0.3-preview-1ee21f9e0
@metamask-previews/profile-sync-controller@29.0.0-preview-1ee21f9e0
@metamask-previews/ramps-controller@20.2.0-preview-1ee21f9e0
@metamask-previews/rate-limit-controller@7.0.1-preview-1ee21f9e0
@metamask-previews/react-data-query@1.0.0-preview-1ee21f9e0
@metamask-previews/remote-feature-flag-controller@6.1.0-preview-1ee21f9e0
@metamask-previews/sample-controllers@5.0.6-preview-1ee21f9e0
@metamask-previews/seedless-onboarding-controller@10.1.1-preview-1ee21f9e0
@metamask-previews/selected-network-controller@26.1.7-preview-1ee21f9e0
@metamask-previews/sentinel-api-service@1.0.1-preview-1ee21f9e0
@metamask-previews/shield-controller@6.0.1-preview-1ee21f9e0
@metamask-previews/signature-controller@39.2.10-preview-1ee21f9e0
@metamask-previews/smart-transactions-controller@26.0.0-preview-1ee21f9e0
@metamask-previews/snap-account-service@2.1.2-preview-1ee21f9e0
@metamask-previews/social-controllers@2.8.0-preview-1ee21f9e0
@metamask-previews/solana-test-validator-up@1.0.0-preview-1ee21f9e0
@metamask-previews/stellar-quickstart-up@0.0.0-preview-1ee21f9e0
@metamask-previews/storage-service@1.0.2-preview-1ee21f9e0
@metamask-previews/subscription-controller@8.0.1-preview-1ee21f9e0
@metamask-previews/transaction-controller@69.7.0-preview-1ee21f9e0
@metamask-previews/transaction-pay-controller@27.1.1-preview-1ee21f9e0
@metamask-previews/user-operation-controller@41.2.9-preview-1ee21f9e0
@metamask-previews/wallet@12.0.2-preview-1ee21f9e0
@metamask-previews/wallet-cli@0.0.0-preview-1ee21f9e0

Jwhiles added a commit to MetaMask/metamask-extension that referenced this pull request Sep 2, 2026
MoneyAccountUpgradeController (core PR MetaMask/core#10072) now owns its
bootstrap: it watches the feature-flag and keyring state, parses the vault
config, and serializes its own re-inits. The extension supplies only the
client-specific parts as hooks — the basic-functionality gate inside
isEnabled, the fail-closed geo check as isEligible, the shared Money chain
configurator, and Sentry reporting for a missing vault config — and
MoneyAccountUpgradeService is deleted.

Per review feedback, no messenger calls happen at construction:
metamask-controller calls controller.init() once everything is built,
alongside the other post-construction init() calls, so the init map no
longer carries ordering constraints. Onboarding and preferences changes
re-trigger the controller's gating through its public sync().

The package is pinned to a preview build until core releases
@metamask/money-account-upgrade-controller@4.0.0 and
@metamask/money-account-utils@1.2.0; the resolutions entries and the
^3.0.2 dependency swap to ^4.0.0 / ^1.2.0 then.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Jwhiles
Jwhiles force-pushed the money-account-upgrade-controller-owned-bootstrap branch from 1ee21f9 to 4258cb1 Compare September 2, 2026 12:25
@Jwhiles
Jwhiles marked this pull request as ready for review September 2, 2026 12:28
@Jwhiles
Jwhiles requested review from a team as code owners September 2, 2026 12:28
@Jwhiles Jwhiles changed the title feat!: make MoneyAccountUpgradeController own its bootstrap feat: make MoneyAccountUpgradeController own its bootstrap Sep 2, 2026
@Jwhiles
Jwhiles force-pushed the money-account-upgrade-controller-owned-bootstrap branch from 4258cb1 to 81700ed Compare September 2, 2026 12:30
ffmcgee725
ffmcgee725 previously approved these changes Sep 2, 2026
@Jwhiles

Jwhiles commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

2 similar comments
@Jwhiles

Jwhiles commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

@Jwhiles

Jwhiles commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

@Jwhiles
Jwhiles force-pushed the money-account-upgrade-controller-owned-bootstrap branch from a302de5 to 6ec257f Compare September 2, 2026 14:08
@Jwhiles

Jwhiles commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

@Jwhiles
Jwhiles force-pushed the money-account-upgrade-controller-owned-bootstrap branch from ad38c64 to ce71f7e Compare September 3, 2026 13:08

@mcmire mcmire left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have one comment below, but everything else seems good to me.

Comment on lines +153 to +157
| ControllerStateChangedEvent<'KeyringController', KeyringControllerState>
| ControllerStateChangedEvent<
'RemoteFeatureFlagController',
RemoteFeatureFlagControllerState
>;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Types already exist for these events, is it possible to use those?

Suggested change
| ControllerStateChangedEvent<'KeyringController', KeyringControllerState>
| ControllerStateChangedEvent<
'RemoteFeatureFlagController',
RemoteFeatureFlagControllerState
>;
type AllowedEvents =
| KeyringControllerStateChangeEvent
| RemoteFeatureFlagControllerStateChangeEvent

(You have may encountered a lint rule prohibiting use of :stateChange events but I plan on removing that.)

mcmire
mcmire previously approved these changes Sep 3, 2026

@mcmire mcmire left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@Jwhiles
Jwhiles enabled auto-merge September 3, 2026 15:34
Matt561
Matt561 previously approved these changes Sep 3, 2026
@Jwhiles
Jwhiles added this pull request to the merge queue Sep 3, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Sep 3, 2026
@Jwhiles
Jwhiles added this pull request to the merge queue Sep 3, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Sep 3, 2026
Jwhiles and others added 10 commits September 4, 2026 09:15
The controller now subscribes to RemoteFeatureFlagController and
KeyringController state, parses the moneyAccountVaultConfig flag, and runs
its own serialized bootstrap, replacing the client-side services that
previously drove init() externally. Client-specific concerns (version-gated
enable flag, eligibility checks, adding the vault chain, error reporting)
are supplied as constructor hooks.

- BREAKING: init() is now the no-argument lifecycle entry point (subscribe
  and sync); the config-arming routine is internal and driven by the
  moneyAccountVaultConfig remote feature flag
- BREAKING: the constructor requires a hooks option with an isEnabled hook
- upgradeAccount() now waits for an in-flight bootstrap instead of
  throwing, and refuses to run against a stale config after the feature is
  disabled
- Add vault-config parsing and comparison helpers to
  @metamask/money-account-utils, shared by the controller and both clients

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A disarm (isEnabled flipping off) or a newer scheduled config during the
CHOMP service-details call now supersedes the in-flight run instead of the
run arming a config the controller had already dropped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Scheduling a bootstrap for a changed vault config now disarms the armed
config, so upgradeAccount waits for the re-bootstrap (or refuses if it
failed) instead of signing delegations against the old vault. The wait also
follows runs chained onto the bootstrap while waiting, so a call that
captured a superseded run no longer throws while its successor is still
running.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Make `underlyingToken` optional in the shared vault-config parser so
  flags that predate the field still parse, matching the balance service
- Re-check the armed config before every upgrade step and abort if it is
  disarmed or superseded mid-sequence
- Refuse `upgradeAccount` while the wallet is locked
- Contain a throwing `onBootstrapError` hook so the failed bootstrap is
  still retried and nothing escapes `init()` or `sync()`

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Jwhiles
Jwhiles dismissed stale reviews from Matt561 and mcmire via 0046818 September 4, 2026 08:16
@Jwhiles
Jwhiles force-pushed the money-account-upgrade-controller-owned-bootstrap branch from 5f5d356 to 0046818 Compare September 4, 2026 08:16

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 0046818. Configure here.

if (!vaultConfig) {
this.#reportMissingConfig();
return;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale vault config stays armed

Medium Severity

When isEnabled is on but moneyAccountVaultConfig is unserved or malformed, sync() reports MissingMoneyAccountVaultConfigError and returns without clearing #config or #bootstrappedConfig. An already-armed controller keeps signing upgrades against the last vault, which contradicts the hook comment that this path disables upgrades and the sibling balance service, which drops the previous vault when the same flag is absent or invalid.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 0046818. Configure here.

@Jwhiles
Jwhiles enabled auto-merge September 4, 2026 08:40
@Jwhiles
Jwhiles added this pull request to the merge queue Sep 4, 2026
Merged via the queue into main with commit bf9a6d4 Sep 4, 2026
50 checks passed
@Jwhiles
Jwhiles deleted the money-account-upgrade-controller-owned-bootstrap branch September 4, 2026 08:44
Jwhiles added a commit to MetaMask/metamask-extension that referenced this pull request Sep 4, 2026
MoneyAccountUpgradeController (core PR MetaMask/core#10072) now owns its
bootstrap: it watches the feature-flag and keyring state, parses the vault
config, and serializes its own re-inits. The extension supplies only the
client-specific parts as hooks — the basic-functionality gate inside
isEnabled, the fail-closed geo check as isEligible, the shared Money chain
configurator, and Sentry reporting for a missing vault config — and
MoneyAccountUpgradeService is deleted.

Per review feedback, no messenger calls happen at construction:
metamask-controller calls controller.init() once everything is built,
alongside the other post-construction init() calls, so the init map no
longer carries ordering constraints. Onboarding and preferences changes
re-trigger the controller's gating through its public sync().

The package is pinned to a preview build until core releases
@metamask/money-account-upgrade-controller@4.0.0 and
@metamask/money-account-utils@1.2.0; the resolutions entries and the
^3.0.2 dependency swap to ^4.0.0 / ^1.2.0 then.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants